//! 重试机制模块
//! 
//! 提供自动重试功能，支持指数退避和自定义重试策略

use crate::{Result, Error, ErrorContext};
use std::time::Duration;
use tokio::time::sleep;
use tracing::{debug, warn};

/// 重试策略配置
#[derive(Debug, Clone)]
pub struct RetryPolicy {
    /// 最大重试次数
    pub max_retries: u32,
    /// 初始等待时间
    pub initial_delay: Duration,
    /// 最大等待时间
    pub max_delay: Duration,
    /// 退避倍数
    pub backoff_multiplier: f64,
    /// 是否添加随机抖动
    pub jitter: bool,
}

impl Default for RetryPolicy {
    fn default() -> Self {
        Self {
            max_retries: 3,
            initial_delay: Duration::from_millis(100),
            max_delay: Duration::from_secs(30),
            backoff_multiplier: 2.0,
            jitter: true,
        }
    }
}

impl RetryPolicy {
    /// 创建快速重试策略（用于轻量级操作）
    pub fn fast() -> Self {
        Self {
            max_retries: 5,
            initial_delay: Duration::from_millis(50),
            max_delay: Duration::from_secs(5),
            backoff_multiplier: 1.5,
            jitter: true,
        }
    }
    
    /// 创建标准重试策略（用于一般操作）
    pub fn standard() -> Self {
        Self::default()
    }
    
    /// 创建慢速重试策略（用于重量级操作）
    pub fn slow() -> Self {
        Self {
            max_retries: 3,
            initial_delay: Duration::from_secs(1),
            max_delay: Duration::from_secs(60),
            backoff_multiplier: 2.0,
            jitter: true,
        }
    }
    
    /// 创建无重试策略
    pub fn none() -> Self {
        Self {
            max_retries: 0,
            initial_delay: Duration::from_millis(0),
            max_delay: Duration::from_millis(0),
            backoff_multiplier: 1.0,
            jitter: false,
        }
    }
    
    /// 计算下次重试的延迟时间
    fn calculate_delay(&self, attempt: u32) -> Duration {
        if attempt == 0 {
            return self.initial_delay;
        }
        
        let base_delay = self.initial_delay.as_millis() as f64 
            * self.backoff_multiplier.powi(attempt as i32);
            
        let delay = Duration::from_millis(base_delay as u64).min(self.max_delay);
        
        if self.jitter {
            // 添加±25%的随机抖动
            let jitter_factor = 1.0 + (rand::random::<f64>() - 0.5) * 0.5;
            Duration::from_millis((delay.as_millis() as f64 * jitter_factor) as u64)
        } else {
            delay
        }
    }
}

/// 重试执行器
#[derive(Clone)]
pub struct RetryExecutor {
    policy: RetryPolicy,
}

impl RetryExecutor {
    /// 创建新的重试执行器
    pub fn new(policy: RetryPolicy) -> Self {
        Self { policy }
    }
    
    /// 创建使用默认策略的执行器
    pub fn default() -> Self {
        Self::new(RetryPolicy::default())
    }
    
    /// 执行可重试的操作
    /// 
    /// # 参数
    /// 
    /// * `operation` - 要执行的异步操作
    /// * `operation_name` - 操作名称（用于日志）
    /// 
    /// # 示例
    /// 
    /// ```rust,no_run
    /// # use koda_sandbox_manager::retry::{RetryExecutor, RetryPolicy};
    /// # use std::time::Duration;
    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
    /// let executor = RetryExecutor::new(RetryPolicy::fast());
    /// 
    /// let result = executor.execute(
    ///     "create_sandbox",
    ///     || async {
    ///         // 可能失败的操作
    ///         Ok(42)
    ///     }
    /// ).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn execute<F, Fut, T>(&self, operation_name: &str, mut operation: F) -> Result<T>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>,
    {
        let mut last_error = None;
        
        for attempt in 0..=self.policy.max_retries {
            debug!(
                operation = operation_name,
                attempt = attempt,
                max_retries = self.policy.max_retries,
                "Executing operation"
            );
            
            match operation().await {
                Ok(result) => {
                    if attempt > 0 {
                        debug!(
                            operation = operation_name,
                            attempt = attempt,
                            "Operation succeeded after retry"
                        );
                    }
                    return Ok(result);
                }
                Err(error) => {
                    last_error = Some(error.clone());
                    
                    // 检查是否可重试
                    if !error.is_retryable() {
                        warn!(
                            operation = operation_name,
                            attempt = attempt,
                            error = %error,
                            error_code = error.error_code(),
                            "Operation failed with non-retryable error"
                        );
                        return Err(error);
                    }
                    
                    // 如果已达到最大重试次数
                    if attempt >= self.policy.max_retries {
                        warn!(
                            operation = operation_name,
                            attempt = attempt,
                            max_retries = self.policy.max_retries,
                            error = %error,
                            error_code = error.error_code(),
                            "Operation failed after all retry attempts"
                        );
                        break;
                    }
                    
                    // 计算延迟并等待
                    let delay = self.policy.calculate_delay(attempt);
                    warn!(
                        operation = operation_name,
                        attempt = attempt,
                        error = %error,
                        error_code = error.error_code(),
                        delay_ms = delay.as_millis(),
                        "Operation failed, retrying after delay"
                    );
                    
                    sleep(delay).await;
                }
            }
        }
        
        // 所有重试都失败了
        let final_error = last_error.unwrap_or_else(|| Error::internal("Unknown error"));
        Err(final_error).context(&format!("Operation '{}' failed after {} retries", operation_name, self.policy.max_retries))
    }
    
    /// 执行可重试的操作，带有自定义重试条件
    pub async fn execute_with_condition<F, Fut, T, C>(
        &self,
        operation_name: &str,
        mut operation: F,
        mut should_retry: C,
    ) -> Result<T>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>,
        C: FnMut(&Error) -> bool,
    {
        let mut last_error = None;
        
        for attempt in 0..=self.policy.max_retries {
            match operation().await {
                Ok(result) => {
                    if attempt > 0 {
                        debug!(
                            operation = operation_name,
                            attempt = attempt,
                            "Operation succeeded after retry"
                        );
                    }
                    return Ok(result);
                }
                Err(error) => {
                    last_error = Some(error.clone());
                    
                    // 检查自定义重试条件
                    if !should_retry(&error) {
                        warn!(
                            operation = operation_name,
                            attempt = attempt,
                            error = %error,
                            "Operation failed with non-retryable condition"
                        );
                        return Err(error);
                    }
                    
                    if attempt >= self.policy.max_retries {
                        break;
                    }
                    
                    let delay = self.policy.calculate_delay(attempt);
                    warn!(
                        operation = operation_name,
                        attempt = attempt,
                        error = %error,
                        delay_ms = delay.as_millis(),
                        "Operation failed with custom condition, retrying"
                    );
                    
                    sleep(delay).await;
                }
            }
        }
        
        let final_error = last_error.unwrap_or_else(|| Error::internal("Unknown error"));
        Err(final_error).context(&format!("Operation '{}' failed after {} retries", operation_name, self.policy.max_retries))
    }
}

/// 重试装饰器trait
/// 
/// 为结构体提供便捷的重试功能
pub trait RetryableOperations {
    /// 执行可重试的操作
    fn retry_operation<F, Fut, T>(&self, operation_name: &str, operation: F) -> impl std::future::Future<Output = Result<T>>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>;
        
    /// 执行快速重试操作
    fn retry_fast<F, Fut, T>(&self, operation_name: &str, operation: F) -> impl std::future::Future<Output = Result<T>>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>;
        
    /// 执行慢速重试操作
    fn retry_slow<F, Fut, T>(&self, operation_name: &str, operation: F) -> impl std::future::Future<Output = Result<T>>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>;
}

/// 默认实现重试装饰器
pub struct DefaultRetryable;

impl RetryableOperations for DefaultRetryable {
    async fn retry_operation<F, Fut, T>(&self, operation_name: &str, operation: F) -> Result<T>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>,
    {
        RetryExecutor::new(RetryPolicy::standard())
            .execute(operation_name, operation)
            .await
    }
    
    async fn retry_fast<F, Fut, T>(&self, operation_name: &str, operation: F) -> Result<T>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>,
    {
        RetryExecutor::new(RetryPolicy::fast())
            .execute(operation_name, operation)
            .await
    }
    
    async fn retry_slow<F, Fut, T>(&self, operation_name: &str, operation: F) -> Result<T>
    where
        F: FnMut() -> Fut,
        Fut: std::future::Future<Output = Result<T>>,
    {
        RetryExecutor::new(RetryPolicy::slow())
            .execute(operation_name, operation)
            .await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::atomic::{AtomicU32, Ordering};
    use std::sync::Arc;
    
    #[test]
    fn test_retry_policy_delay_calculation() {
        let policy = RetryPolicy {
            max_retries: 3,
            initial_delay: Duration::from_millis(100),
            max_delay: Duration::from_secs(10),
            backoff_multiplier: 2.0,
            jitter: false,
        };
        
        assert_eq!(policy.calculate_delay(0), Duration::from_millis(100));
        assert_eq!(policy.calculate_delay(1), Duration::from_millis(200));
        assert_eq!(policy.calculate_delay(2), Duration::from_millis(400));
    }
    
    #[test]
    fn test_retry_policy_max_delay() {
        let policy = RetryPolicy {
            max_retries: 10,
            initial_delay: Duration::from_millis(1000),
            max_delay: Duration::from_secs(5),
            backoff_multiplier: 2.0,
            jitter: false,
        };
        
        // 第3次重试应该达到max_delay
        let delay = policy.calculate_delay(3);
        assert!(delay <= Duration::from_secs(5));
    }
    
    #[tokio::test]
    async fn test_retry_executor_success_immediately() {
        let executor = RetryExecutor::new(RetryPolicy::fast());
        let counter = Arc::new(AtomicU32::new(0));
        
        let result = executor.execute(
            "test_operation",
            {
                let counter = counter.clone();
                move || {
                    let counter = counter.clone();
                    async move {
                        counter.fetch_add(1, Ordering::SeqCst);
                        Ok::<i32, Error>(42)
                    }
                }
            }
        ).await;
        
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 42);
        assert_eq!(counter.load(Ordering::SeqCst), 1);
    }
    
    #[tokio::test]
    async fn test_retry_executor_success_after_retries() {
        let executor = RetryExecutor::new(RetryPolicy {
            max_retries: 3,
            initial_delay: Duration::from_millis(1), // 快速测试
            max_delay: Duration::from_millis(10),
            backoff_multiplier: 1.0,
            jitter: false,
        });
        
        let counter = Arc::new(AtomicU32::new(0));
        
        let result = executor.execute(
            "test_operation",
            {
                let counter = counter.clone();
                move || {
                    let counter = counter.clone();
                    async move {
                        let count = counter.fetch_add(1, Ordering::SeqCst);
                        if count < 2 {
                            Err(Error::timeout("Simulated timeout"))
                        } else {
                            Ok(42)
                        }
                    }
                }
            }
        ).await;
        
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 42);
        assert_eq!(counter.load(Ordering::SeqCst), 3); // 2次失败 + 1次成功
    }
    
    #[tokio::test]
    async fn test_retry_executor_non_retryable_error() {
        let executor = RetryExecutor::new(RetryPolicy::fast());
        let counter = Arc::new(AtomicU32::new(0));
        
        let result: Result<i32> = executor.execute(
            "test_operation",
            {
                let counter = counter.clone();
                move || {
                    let counter = counter.clone();
                    async move {
                        counter.fetch_add(1, Ordering::SeqCst);
                        Err(Error::ConfigFormat) // 不可重试的错误
                    }
                }
            }
        ).await;
        
        assert!(result.is_err());
        assert_eq!(counter.load(Ordering::SeqCst), 1); // 只执行一次
    }
    
    #[tokio::test]
    async fn test_retry_executor_max_retries_exceeded() {
        let executor = RetryExecutor::new(RetryPolicy {
            max_retries: 2,
            initial_delay: Duration::from_millis(1),
            max_delay: Duration::from_millis(10),
            backoff_multiplier: 1.0,
            jitter: false,
        });
        
        let counter = Arc::new(AtomicU32::new(0));
        
        let result: Result<i32> = executor.execute(
            "test_operation",
            {
                let counter = counter.clone();
                move || {
                    let counter = counter.clone();
                    async move {
                        counter.fetch_add(1, Ordering::SeqCst);
                        Err(Error::timeout("Always fails"))
                    }
                }
            }
        ).await;
        
        assert!(result.is_err());
        assert_eq!(counter.load(Ordering::SeqCst), 3); // 原始执行 + 2次重试
    }
}